package demo;

/**
 * Created with IntelliJ IDEA
 * Description:
 * User:34398
 * Date:2024-07-25
 * Time:15:25
 */

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * 两个队列不可能即是空，又是满（不可能都wait）
 */
//class MyBlockingQueue {
//
//    //循环队列实现
//    String[] data = null;
//
//    public MyBlockingQueue(int capacity) {
//        this.data = new String[capacity];
//    }
//
//
//    //[head,tail) ---->左闭右开
//    int head = 0, tail = 0, useSize = 0;
//
//    public void put(String s) throws InterruptedException {
//        synchronized (this) {
//            while (useSize == data.length) {
//                this.wait();//满了就停下，等take方法拿走一个元素先
//            }
//            data[tail] = s;
//            tail++;
//            if (tail >= data.length) tail = 0;//循环
//            this.notify();
//            useSize++;
//        }
//    }
//
//    public String take() throws InterruptedException {
//        synchronized (this) {
//            while (useSize == 0) {
//                this.wait();//空的时候停下，等put出元素，然后再开始
//            }
//            String ret = data[head];
//            head++;
//            if (head >= data.length) {
//                head = 0;
//            }
//            useSize--;
//            this.notify();//记得通知一下，如果没有也没有影响
//            return ret;
//        }
//    }
//
//
//}

class MyBlockingQueue {
    //用数组实现
    String[] data = null;

    //分别表示头、尾、队列长度
    int head = 0, tail = 0, useSize = 0;
    /**指向有效元素的指针是左闭右开的，[head,tail)
     * tail端put进
     * head端take出*/



    //构造方法，设置最大容量
    public MyBlockingQueue(int capacity) {
        this.data = new String[capacity];
    }

    //插入方法
    public void put(String s) throws InterruptedException {
//        //如果队列满了，不做处理
//        if(useSize==data.length)return;

     synchronized(this){/**this指的是当前类，创建的一个实例，其他实例对象也可以，只要对象是匹配的*/
         while(useSize==data.length){
             this.wait();//让当前线程先睡眠，等其他线程take元素了，然后再唤醒它
         }
         data[tail]=s;//直接赋值，因为tail区间是开的
         tail++;
         if(tail>=data.length)tail=0;
         useSize++;//记得长度加一
         this.notify();//put完了，反过来通知take
     }
    }

    //取出方法
    public String take() throws InterruptedException {

//        //没有就取不出来
//        if(useSize==0)return null;


        synchronized(this){
            while(useSize==0){
                this.wait();
            }

            String ret=data[head];
            head++;
            if(head>=data.length)head=0;
            useSize--;
            this.notify();//take完了，通知一下put
            return ret;
        }
    }
}

public class MYblockingQueue {
    public static void main(String[] args) {
        MyBlockingQueue blockingQueue=new MyBlockingQueue(1000);

        Thread thread1=new Thread(()->{
            int i=0;
            while(true){
                i++;
                System.out.println("生产一个元素："+i);
                try {
                    blockingQueue.put(""+i);
                } catch (InterruptedException e) {//调用put或者take都需要处理中断异常
                    e.printStackTrace();
                }
            }
        });

        Thread thread2=new Thread(()->{
            while(true){
                try {
                    String i=blockingQueue.take();
                    Thread.sleep(1000);//模拟消费者处理速度慢的情况
                    System.out.println("消费一个元素："+i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });
        thread1.start();
        thread2.start();

    }

}
